import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
import java.nio.ByteOrder;
import java.util.Random;
import util.UnsafeUtil;

public class ReadInt {
	static final int TEST_COUNT = 1000;
	static final VarHandle intLeHandler = MethodHandles.byteArrayViewVarHandle(int[].class, ByteOrder.LITTLE_ENDIAN);

	static int SumSafe1(byte[] data) {
		var r = 0;
		for (var j = 0; j < TEST_COUNT; j++) {
			for (int i = 0, n = data.length - 4; i < n; i++)
				r += (data[i] & 0xff) + ((data[i + 1] & 0xff) << 8) + ((data[i + 2] & 0xff) << 16) + (data[i + 3] << 24);
		}
		return r;
	}

	static int SumSafe2(byte[] data) {
		var r = 0;
		for (var j = 0; j < TEST_COUNT; j++) {
			for (int i = 0, n = data.length - 4; i < n; i++)
				r += (int)intLeHandler.get(data, i);
		}
		return r;
	}

	@SuppressWarnings("removal")
	static int SumUnsafe(byte[] data) {
		var r = 0;
		for (var j = 0; j < TEST_COUNT; j++) {
			for (int i = 0, n = data.length - 4; i < n; i++)
				r += UnsafeUtil.unsafe.getInt(data, UnsafeUtil.ARRAY_BYTE_BASE_OFFSET + i);
		}
		return r;
	}

	static void test(byte[] data) {
		var t = System.currentTimeMillis();
		var r = SumSafe1(data);
		System.out.println("SumSafe1 : " + r + ", time: " + (System.currentTimeMillis() - t));

		t = System.currentTimeMillis();
		r = SumSafe2(data);
		System.out.println("SumSafe2 : " + r + ", time: " + (System.currentTimeMillis() - t));

		t = System.currentTimeMillis();
		r = SumUnsafe(data);
		System.out.println("SumUnsafe: " + r + ", time: " + (System.currentTimeMillis() - t));
	}

	public static void main(String[] args) {
		var data = new byte[1 << 20];
		new Random().nextBytes(data);

		for (int i = 0; i < 5; i++) {
			test(data);
			System.out.println("---");
		}
	}
}
